//
//  user.v
//
//  Generische Slave-Mode Anwendung: Realisiert ein les-/schreibbares
//  Hardware-Register
//

module user(
	    CLK,
	    RESET,  
	    ADDRESSED,
	    WRITE,
	    DATAIN,
	    DATAOUT,
	    ADDRESS,
	    IRQ
	    );

   // Eingaenge
   input           CLK;
   input           RESET;
   input           ADDRESSED;
   input           WRITE;
   input [31:0]    DATAIN;
   input [23:2]    ADDRESS;

   // Ausgaenge
   output [31:0]   DATAOUT;
   output          IRQ;

   wire 	   IRQ = 1'b0; // wird im Slave-Mode nicht gebraucht

   // Beginn der Anwendung **************************************************
   reg [31:0] 	   data;
   wire [31:0] 	   result;          // Ergebnisregister
   reg [7:0] 	   minimum, maximum;

   reg [15:0] 	   dividend;
   reg [7:0] 	   divisor;
   wire [15:0] 	   quot;
   wire [7:0] 	   remd;

   reg [15:0] 	   stepSize;
   reg [4:0] 	   addresses [0:17];

   localparam noAddress = 32;
   localparam stepSizeAddress = 31;

   assign result = (((data-minimum) << 4)*stepSize)>>8;
   
   generate
      genvar 	   i;
      for (i = 1; i < 18; i = i + 1) begin
	 always @(posedge CLK or posedge RESET) begin
	    if ((RESET) || (WRITE == 0)) begin
	       addresses[i] <= noAddress;
	    end else begin
	       addresses[i] <= addresses[i - 1];
	    end
	 end
      end
   endgenerate
   
   PipelinedDivider pd(.dividend(dividend),
		       .divisor(divisor),
		       .quot(quot),
		       .remd(remd),
		       .clk(CLK),
		       .rfd());
   
   // Ausgabedaten auf Bus legen
   assign DATAOUT = result;

   // Steuerung
   always @(posedge CLK or posedge RESET) begin
      
      // Initialisiere Register
      if (RESET) begin
	 data  <= 8'h00;
	 minimum = 255;
	 maximum = 0;
	 addresses[0] <= noAddress;
	 dividend <= 16'hFFFF;
	 divisor <= 8'h01;
	 // Schreibzugriff auf RC
      end else begin
	 
	 if (addresses[17] == stepSizeAddress) begin
	    stepSize <= quot;
	 end
	 
	 if (ADDRESSED & WRITE) begin
	    if (ADDRESS[7:2] == stepSizeAddress) begin
	       if (DATAIN > maximum) begin
		  maximum = DATAIN;
	       end
	       if (DATAIN < minimum) begin
		  minimum = DATAIN;
	       end
	       dividend <= 255 << 4;
	       divisor <= (maximum - minimum);
	       addresses[0] <= stepSizeAddress;			  
	    end else if (ADDRESS[7:2] == 0) begin
	       data <= DATAIN;
	    end
	 end
	 
      end
      
   end

endmodule
